from django.db import models
from django.core.exceptions import ValidationError
from django.db import transaction
from django.utils import timezone
from datetime import datetime
from base import models as baseModels
from store import models as storeModels
# Create your models here.
# 1. 自定义入库单表单，添加校验逻辑

class InvoicePackagingModel(models.Model):
    '''发票管理-包材'''
    # 将原来的standard字符字段改为外键关联到StandardModel
    store_orders = models.ManyToManyField(
        storeModels.StorePackagingOrderModel,
        verbose_name='包材入库单号'
    )
    invoice_num = models.CharField(max_length=255, verbose_name='发票号', default='',null=True,blank=True,unique=True)
    amount = models.DecimalField(verbose_name='含税金额', max_digits=10,decimal_places=2)
    remark = models.CharField(max_length=255, verbose_name='备注', default='',null=True,blank=True)


    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='包材开票管理'
        verbose_name_plural = verbose_name  # 自定义复数形式，与单数相同




    def clean(self):
        """模型验证方法，用于检查保存条件"""


        # 补充验证：开票金额不能为负数
        if self.amount is not None and self.amount < 0:
            raise ValidationError({"amount": "开票金额不能为负数！"})



    def save(self, *args, **kwargs):
        # 先执行验证（但不强制在事务中先验证，避免多对多关联检查时主模型未保存）
        self.full_clean(exclude=['store_orders'])  # 排除多对多字段的验证，避免未保存时的错误

        with transaction.atomic():
            super().save(*args, **kwargs)



    def delete(self, *args, **kwargs):
        with transaction.atomic():
            # 如果有库存相关逻辑，在此处处理
            super().delete(*args, **kwargs)

    @classmethod
    def bulk_delete_with_logic(cls, queryset):
        """批量删除并处理关联逻辑"""
        with transaction.atomic():
            # 处理批量删除前的业务逻辑
            queryset.delete()

class InvoiceRawModel(models.Model):
    '''发票管理-包材'''
    # 将原来的standard字符字段改为外键关联到StandardModel
    store_orders = models.ManyToManyField(
        storeModels.StoreRawOrderModel,
        verbose_name='原料入库单号'
    )
    invoice_num = models.CharField(max_length=255, verbose_name='发票号', default='',null=True,blank=True,unique=True)
    amount = models.DecimalField(verbose_name='含税金额', max_digits=10,decimal_places=2)
    remark = models.CharField(max_length=255, verbose_name='备注', default='',null=True,blank=True)


    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='原料开票管理'
        verbose_name_plural = verbose_name  # 自定义复数形式，与单数相同




    def clean(self):
        """模型验证方法，用于检查保存条件"""


        # 补充验证：开票金额不能为负数
        if self.amount is not None and self.amount < 0:
            raise ValidationError({"amount": "开票金额不能为负数！"})



    def save(self, *args, **kwargs):
        # 先执行验证（但不强制在事务中先验证，避免多对多关联检查时主模型未保存）
        self.full_clean(exclude=['store_orders'])  # 排除多对多字段的验证，避免未保存时的错误

        with transaction.atomic():
            super().save(*args, **kwargs)



    def delete(self, *args, **kwargs):
        with transaction.atomic():
            # 如果有库存相关逻辑，在此处处理
            super().delete(*args, **kwargs)

    @classmethod
    def bulk_delete_with_logic(cls, queryset):
        """批量删除并处理关联逻辑"""
        with transaction.atomic():
            # 处理批量删除前的业务逻辑
            queryset.delete()

class InvoiceAdditiveModel(models.Model):
    '''发票管理-包材'''
    # 将原来的standard字符字段改为外键关联到StandardModel
    store_orders = models.ManyToManyField(
        storeModels.StoreAdditiveOrderModel,
        verbose_name='添加剂入库单号'
    )
    invoice_num = models.CharField(max_length=255, verbose_name='发票号', default='',null=True,blank=True,unique=True)
    amount = models.DecimalField(verbose_name='含税金额', max_digits=10,decimal_places=2)
    remark = models.CharField(max_length=255, verbose_name='备注', default='',null=True,blank=True)


    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='添加剂开票管理'
        verbose_name_plural = verbose_name  # 自定义复数形式，与单数相同




    def clean(self):
        """模型验证方法，用于检查保存条件"""


        # 补充验证：开票金额不能为负数
        if self.amount is not None and self.amount < 0:
            raise ValidationError({"amount": "开票金额不能为负数！"})



    def save(self, *args, **kwargs):
        # 先执行验证（但不强制在事务中先验证，避免多对多关联检查时主模型未保存）
        self.full_clean(exclude=['store_orders'])  # 排除多对多字段的验证，避免未保存时的错误

        with transaction.atomic():
            super().save(*args, **kwargs)



    def delete(self, *args, **kwargs):
        with transaction.atomic():
            # 如果有库存相关逻辑，在此处处理
            super().delete(*args, **kwargs)

    @classmethod
    def bulk_delete_with_logic(cls, queryset):
        """批量删除并处理关联逻辑"""
        with transaction.atomic():
            # 处理批量删除前的业务逻辑
            queryset.delete()


class PaymentRawModel(models.Model):
    '''付款管理-原料'''
    # 将原来的standard字符字段改为外键关联到StandardModel
    supplier = models.ForeignKey(
        baseModels.SupplierRawModel,
        verbose_name='供应商',
        null = False, blank = False,
        on_delete=models.CASCADE,
    )
    invoice_num = models.CharField(max_length=255, verbose_name='发票号', default='',null=True,blank=True,unique=True)
    amount = models.DecimalField(verbose_name='含税金额', max_digits=10,decimal_places=2)
    remark = models.CharField(max_length=255, verbose_name='备注', default='',null=True,blank=True)


    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='原料付款管理'
        verbose_name_plural = verbose_name  # 自定义复数形式，与单数相同




    def clean(self):
        """模型验证方法，用于检查保存条件"""


        # 补充验证：开票金额不能为负数
        if self.amount is not None and self.amount < 0:
            raise ValidationError({"amount": "开票金额不能为负数！"})



    def save(self, *args, **kwargs):
        # 先执行验证（但不强制在事务中先验证，避免多对多关联检查时主模型未保存）
        self.full_clean(exclude=['store_orders'])  # 排除多对多字段的验证，避免未保存时的错误

        with transaction.atomic():
            super().save(*args, **kwargs)



    def delete(self, *args, **kwargs):
        with transaction.atomic():
            # 如果有库存相关逻辑，在此处处理
            super().delete(*args, **kwargs)

    @classmethod
    def bulk_delete_with_logic(cls, queryset):
        """批量删除并处理关联逻辑"""
        with transaction.atomic():
            # 处理批量删除前的业务逻辑
            queryset.delete()

class PaymentAdditiveModel(models.Model):
    '''付款管理-原料'''
    # 将原来的standard字符字段改为外键关联到StandardModel
    supplier = models.ForeignKey(
        baseModels.SupplierAdditiveModel,
        verbose_name='供应商',
        null = False, blank = False,
        on_delete=models.CASCADE,
    )
    invoice_num = models.CharField(max_length=255, verbose_name='发票号', default='',null=True,blank=True,unique=True)
    amount = models.DecimalField(verbose_name='含税金额', max_digits=10,decimal_places=2)
    remark = models.CharField(max_length=255, verbose_name='备注', default='',null=True,blank=True)


    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='添加剂付款管理'
        verbose_name_plural = verbose_name  # 自定义复数形式，与单数相同




    def clean(self):
        """模型验证方法，用于检查保存条件"""


        # 补充验证：开票金额不能为负数
        if self.amount is not None and self.amount < 0:
            raise ValidationError({"amount": "开票金额不能为负数！"})



    def save(self, *args, **kwargs):
        # 先执行验证（但不强制在事务中先验证，避免多对多关联检查时主模型未保存）
        self.full_clean(exclude=['store_orders'])  # 排除多对多字段的验证，避免未保存时的错误

        with transaction.atomic():
            super().save(*args, **kwargs)



    def delete(self, *args, **kwargs):
        with transaction.atomic():
            # 如果有库存相关逻辑，在此处处理
            super().delete(*args, **kwargs)

    @classmethod
    def bulk_delete_with_logic(cls, queryset):
        """批量删除并处理关联逻辑"""
        with transaction.atomic():
            # 处理批量删除前的业务逻辑
            queryset.delete()

class PaymentPackagingModel(models.Model):
    '''付款管理-原料'''
    # 将原来的standard字符字段改为外键关联到StandardModel
    supplier = models.ForeignKey(
        baseModels.SupplierAdditiveModel,
        verbose_name='供应商',
        null = False, blank = False,
        on_delete=models.CASCADE,
    )
    invoice_num = models.CharField(max_length=255, verbose_name='发票号', default='',null=True,blank=True,unique=True)
    amount = models.DecimalField(verbose_name='含税金额', max_digits=10,decimal_places=2)
    remark = models.CharField(max_length=255, verbose_name='备注', default='',null=True,blank=True)


    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='包材付款管理'
        verbose_name_plural = verbose_name  # 自定义复数形式，与单数相同




    def clean(self):
        """模型验证方法，用于检查保存条件"""


        # 补充验证：开票金额不能为负数
        if self.amount is not None and self.amount < 0:
            raise ValidationError({"amount": "开票金额不能为负数！"})



    def save(self, *args, **kwargs):
        # 先执行验证（但不强制在事务中先验证，避免多对多关联检查时主模型未保存）
        self.full_clean(exclude=['store_orders'])  # 排除多对多字段的验证，避免未保存时的错误

        with transaction.atomic():
            super().save(*args, **kwargs)



    def delete(self, *args, **kwargs):
        with transaction.atomic():
            # 如果有库存相关逻辑，在此处处理
            super().delete(*args, **kwargs)

    @classmethod
    def bulk_delete_with_logic(cls, queryset):
        """批量删除并处理关联逻辑"""
        with transaction.atomic():
            # 处理批量删除前的业务逻辑
            queryset.delete()